﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.Text.RegularExpressions;

namespace MEMDB
{
    public partial class MainFrame : Form
    {
        //static MailGirl mailGirl = new MailGirl();
        static Startup startUp = new Startup();
        static bool isConnected = false;
        static bool hasPasted = false;
        SQLConnection con = new SQLConnection();

        Font keyFont = new Font("微软雅黑", 11, FontStyle.Regular);
        Font normalFont = new Font("微软雅黑", 11, FontStyle.Regular);

        delegate void SetProgressbarCallback(Boolean b);
        delegate void SetTabIndexCallback(Int32 i);
        delegate void AppendMsgCallback(String s);
        delegate void ShowCodeLineCallback(int row, int column);

        List<String> keyWords;

        public MainFrame()
        {
            InitializeComponent();
            this.contextMenuStrip1.Enabled = false;
            this.timer1.Start();
            progressBar1.Visible = false;
            this.progressBar1.MarqueeAnimationSpeed = 20;
            string[] keystr = {
            "select", 
             "from",
             "where",
             "update",
             "set",
             "insert",
             "delete",
             "connect",
              "run",
             "and",
             "or",
             "values",
             "into",
             "to",
             "server",
             "user",
             "password",
             "create",
             "database",
             "table",
             "not",
             "null",
             "default",
             "primary",
             "key",
             "max_size",
             "on",
             "log",
             "varchar2",
             "int",
             "number",
             "using",
             "save",
             "exit",
             "load",
             "qsysteminfo",
             "login",
             "as",
             "nodb",
             "drop",
             "startup",
             "passwd",
             "close",
             "peer",
             "=",
             ">",
             "<",
            };
            this.keyWords = new List<String>(keystr);
            this.rtbCmd.SelectionFont = normalFont;
        }

        private void MainFrame_Load(object sender, EventArgs e)
        {
        }

        //返回搜索字符
        public static string GetLastWord(string str)
       { 
            string x = str;
            Regex reg = new Regex(@"\b[a-zA-Z0-9_]+\b", RegexOptions.RightToLeft);
            x = reg.Match(x).Value;
            Regex reg2 = new Regex(@"\s");
            x = reg2.Replace(x, "");
            return x;
        }


        public void setProgressbar(Boolean isVisible)
        {
            this.progressBar1.Visible = isVisible;
            if (isVisible)
            {
                this.toolStripStatusLabel1.Text = "连接中...";
            }
            else
            {
                this.toolStripStatusLabel1.Text = "已连接";
            }
        }

        public DataGridView getTableView()
        {
            return dataGridView1;
        }


        public void connect()
        {
            startUp.ShowDialog();
            startUp.Focus();
            if (!startUp.isPassed())
            {
                System.Environment.Exit(0);
            }
            SetProgressbarCallback setProgress = new SetProgressbarCallback(setProgressbar);
            while (!this.IsHandleCreated) ;
            this.Invoke(setProgress, true);
            con.ConnectString = startUp.getConnString();
            String strMsg = "";
            while (_con(startUp.getIp(), startUp.getPort(), startUp.getConnString(), ref strMsg) == false)
            {
                while (!this.IsHandleCreated) ;
                this.Invoke(setProgress, false);
                String strTemp = "\0";
                strMsg.TrimEnd(strTemp.ToCharArray());
                startUp.setMessage(strMsg);
                startUp.Text = "Connect failed.";
                startUp.Refresh();
                startUp.Focus();
                startUp.ShowDialog();
                if (!startUp.isPassed())
                {
                    System.Environment.Exit(0);
                }
                con.ConnectString = startUp.getConnString();
                this.Invoke(setProgress, true);
            }
            isConnected = true;
            AppendMsgCallback appendMsgC = new AppendMsgCallback(appendMsg);
            this.Invoke(appendMsgC, "登陆成功。");
            this.Invoke(setProgress, false);
        }

        public bool _con(IPAddress ipAddr, int port, string loginString, ref String strMsg)
        {
            try
            {
                return con.Login(ipAddr, port, loginString, ref strMsg);
            }
            catch (System.Exception ex)
            {
                if (ex is SQLException)
                {
                    return false;
                }
                MessageBox.Show(ex.ToString());
                return false;
            }
        }

        public void checkConnection()
        {
            if (hasPasted)
            {
                updateCodeColor();
                hasPasted = false;
            }
            updatePositionThread();
            if (isConnected)
            {
                数据库ToolStripMenuItem.Enabled = true;
                表ToolStripMenuItem.Enabled = true;
                登陆ToolStripMenuItem.Enabled = false;
                ConnectToolStripButton2.Enabled = false;
                断开ToolStripMenuItem.Enabled = true;
                DisconToolStripButton3.Enabled = true;
                contextMenuStrip1.Enabled = true;
                toolStripButton2.Enabled = true;
                toolStripButton1.Enabled = true;
                执行选中toolStripButton1.Enabled = true;
                CommitToolStripButton1.Enabled = true;
                复制toolStripButton1.Enabled = true;
                剪切toolStripButton1.Enabled = true;
                粘贴toolStripButton1.Enabled = true;
            }
            else
            {
                数据库ToolStripMenuItem.Enabled = false;
                表ToolStripMenuItem.Enabled = false;
                登陆ToolStripMenuItem.Enabled = true;
                if (startUp.Visible != true)
                {
                    ConnectToolStripButton2.Enabled = true;
                }
                断开ToolStripMenuItem.Enabled = false;
                DisconToolStripButton3.Enabled = false;
                toolStripButton1.Enabled = false;
                执行选中toolStripButton1.Enabled = false;
                CommitToolStripButton1.Enabled = false;
                复制toolStripButton1.Enabled = false;
                剪切toolStripButton1.Enabled = false;
                粘贴toolStripButton1.Enabled = false;
                toolStripButton2.Enabled = false;
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            checkConnection();
        }
        public void appendMsg(string msg)
        {
            lbMsg.Text += "\r\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\r\n";
            lbMsg.Text += ("\r\n" + msg + "\r\n");
            lbMsg.Text += "\r\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\r\n";
            lbMsg.Select(lbMsg.TextLength, 0);
            lbMsg.ScrollToCaret();
        }

        public void updateCodeLine(int row, int column)
        {
            this.toolStripStatusLabel2.Text = row + " 行 " + column + " 列";
        }

        private void 执行语句ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            string cmd = rtbCmd.Text.Substring(rtbCmd.SelectionStart, rtbCmd.SelectionLength);
            execute(cmd);
            this.Cursor = Cursors.Default;
        }

        private void 执行所有ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            execute(rtbCmd.Text.Trim());
            this.Cursor = Cursors.Default;
        }

        private string GetCommandStatement(string commandString, int index)
        {
            string str = null;
            for (int i = index; i < commandString.Length && commandString[i] != ';' && commandString[i] != '\0'; i++)
            {
                str += commandString[i];
            }
            str += ';';
            return str;
        }

        public bool ExecuteBatchQuery(string cmdStr)
        {
            cmdStr.Trim(new char[] { '\n', '\t', ' ', '\r' });
            string statement;
            int iIndex = 0;
            while (iIndex < cmdStr.Length)
            {
                statement = GetCommandStatement(cmdStr, iIndex);
                if (statement != null)
                {
                    statement = statement.Trim(new char[] { '\n', '\t', ' ', '\r' });
                    if (statement.Length > 0)
                    {
                        iIndex += statement.Length + 1;
                        string str = SQLCommand.GetParameterName(statement, 0);
                        if (str.Trim().ToLower().Equals("select"))
                        {
                            SQLCommand cmd = new SQLCommand(statement, con);
                            ResultDataSet DataSet = new ResultDataSet();
                            try
                            {
                                DataSet = cmd.ExecuteQuery();
                                if (DataSet != null && !DataSet.isEmpty())
                                {
                                    DataSet.FillGridView(this.getDataGridView());
                                    this.appendMsg(cmd.getRetMsg());
                                }
                                else
                                {
                                    //执行失败，返回
                                    this.getDataGridView().Columns.Clear();
                                    this.getDataGridView().Rows.Clear();
                                    this.appendMsg(cmd.getRetMsg());
                                    return false;
                                }
                            }
                            catch (SQLException ex)
                            {
                                MessageBox.Show(ex.Message);
                                return false;
                            }
                        }
                        else
                        {
                            SQLCommand cmd = new SQLCommand(statement, con);
                            try
                            {
                              cmd.ExecuteNonQuery(); 
                              this.appendMsg(cmd.getRetMsg());
                            }
                            catch (SQLException ex)
                            {
                                MessageBox.Show(ex.Message);
                                return false;
                            }
                        }
                    }
                }
            }
            return true;
        }


        public void execute(string cmdStr)
        {
            cmdStr = cmdStr.Trim(new char[] { ' ', '\r', '\t', '\n' });
            if (cmdStr.Length < 1)
            {
                return;
            }
            try
            {
                if (cmdStr.ToLower().Equals("peer;"))
                {
                    SQLCommand cmdPeer = new SQLCommand(cmdStr, con);
                    this.appendMsg(cmdPeer.GetDBInfo());
                    return;
                }

                if (this.ExecuteBatchQuery(cmdStr))
                {
                    // this.appendMsg("语句全部执行成功。");
                }
                else
                {
                    //this.appendMsg("由于途中某个语句错误，语句没有完全执行。");
                }
            }
            catch (SQLException ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void 粘贴ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SendKeys.Send("^v");
            hasPasted = true;
            //this.updateCodeColor();
         
        }

        public TextBox getMsgLabel()
        {
            return lbMsg;
        }

        private void MainFrame_Resize(object sender, EventArgs e)
        {
            foreach (TabPage page in this.tabControl1.TabPages)
            {
                page.Refresh();
            }
        }


        public DataGridView getDataGridView()
        {
            return this.dataGridView1;
        }

        public void setTabIndex(int i)
        {
            if (i > -1 && i < 2)
            {
                this.tabControl1.SelectedIndex = i;
            }
        }

        private void MainFrame_Shown(object sender, EventArgs e)
        {
            Thread connThrd = new Thread(new ThreadStart(connect));
            connThrd.Start();
        }

        private void MainFrame_FormClosed(object sender, FormClosedEventArgs e)
        {
            this.con.Close();
            isConnected = false;
            System.Environment.Exit(0);
        }

        private void 创建表ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CreateTable ct = new CreateTable(con);
            ct.ShowDialog();
            this.appendMsg(ct.getMsg());
        }

        private void 复制ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SendKeys.Send("^c");
        }

        private void 剪切ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SendKeys.Send("^x");
        }

        private void dataGridView1_ColumnAdded(object sender, DataGridViewColumnEventArgs e)
        {
            SetTabIndexCallback setTabIndexC = new SetTabIndexCallback(setTabIndex);
            this.Invoke(setTabIndexC, 0);
        }

        private void lbMsg_TextChanged(object sender, EventArgs e)
        {
            SetTabIndexCallback setTabIndexC = new SetTabIndexCallback(setTabIndex);
            this.Invoke(setTabIndexC, 1);
        }

        private void 登陆ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Thread connThrd = new Thread(new ThreadStart(connect));
            connThrd.Start();
        }

        private void 断开ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            con.Close();
            isConnected = false;
            this.appendMsg("断开成功。");
            this.toolStripStatusLabel1.Text = "未连接";
        }

        private void 创建数据库ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CreateDatabase cd = new CreateDatabase(con);
            cd.ShowDialog();
            if (cd.Successful)
            {
                this.appendMsg("创建数据库成功。");
            }
            else
            {
                this.appendMsg("创建数据库失败。");
            }
        }

        private void 删除数据库ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            String dbList = "";
            SQLCommand cmd = new SQLCommand("qsysteminfo;------------------------------------------", con);
            try
            {
                cmd.ExecuteNonQuery();
                dbList = cmd.getRetMsg();
                DeleteDatabase delDb = new DeleteDatabase(dbList, con);
                delDb.ShowDialog();
                if (delDb.Successful)
                {
                    this.appendMsg("删除数据库成功");
                }
                else
                {
                    this.appendMsg("删除数据库失败");
                }
            }
            catch (SQLException ex)
            {
                MessageBox.Show("连接已关闭。");
                isConnected = false;
            }
        }

        private void 删除表ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            String tbList = "";
            SQLCommand cmd = new SQLCommand("peer;------------------------------------------", con);
            try
            {
                cmd.ExecuteNonQuery();
                tbList = cmd.getRetMsg();
                DeleteTable dt = new DeleteTable(tbList, con);
                dt.ShowDialog();
                this.appendMsg(dt.getMsg());
            }
            catch (SQLException ex)
            {
                MessageBox.Show(ex.Message);
            }

        }

        private void 帮助ToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        public string GetWord(String s)
        {
            string x = s;
            Regex reg = new Regex(@"\b[a-zA-Z0-9_]+\b", RegexOptions.RightToLeft);
            x = reg.Match(x).Value;
            if (x.Equals(""))
            {
                return null;
            }
            return x;
        }
        private void updateCodeColor()
        {
            int startIndex = this.rtbCmd.SelectionStart;　　//记录修改的位置
            int i = 0;
            string s;
            while (( s = GetWord(this.rtbCmd.Text.Substring(i))) != null)
            {
                s = s.ToLower();
                if (keyWords.IndexOf(s) > -1)
                {
                    this.rtbCmd.Select(i, s.Length);
                    this.rtbCmd.SelectionFont = keyFont;
                }
                else
                {
                    this.rtbCmd.Select(i, s.Length);
                    this.rtbCmd.SelectionFont = normalFont;
                }
                i += s.Length;
            }
            this.rtbCmd.Select(startIndex, 0);　　 //返回修改的位置
            this.rtbCmd.SelectionColor = Color.Black;
            this.rtbCmd.SelectionFont = normalFont;
        }

        private void CommitToolStripButton1_Click(object sender, EventArgs e)
        {
            SQLCommand cmd = new SQLCommand("commit;", con);
            try
            {
                cmd.ExecuteNonQuery();
                this.appendMsg(cmd.getRetMsg());
            }
            catch (SQLException ex)
            {
                MessageBox.Show("提交失败。原因:" + ex.Message);
                this.appendMsg("提交失败。原因:" + ex.Message);
            }
        }

        public void updatePositionThread()
        {
            int begin = 0;
            int fronting = rtbCmd.SelectionStart;
            int row = rtbCmd.GetLineFromCharIndex(rtbCmd.SelectionStart);
            while (begin < fronting)
            {
                if (row == rtbCmd.GetLineFromCharIndex(begin)) //richTextBox的GetLineFormCharIndex()方法，获取行号 
                {
                    break;
                }
                else
                {
                    begin++;
                }
            }
            int column = fronting - begin;
            row++;
            column++;
            this.updateCodeLine(row, column);
        }


        //加入控制字体，颜色代码。
        private void rtbCmd_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter
           || e.KeyCode == Keys.Space
          || e.KeyCode == Keys.Tab
                ||e.KeyCode == Keys.OemOpenBrackets
                || e.KeyCode == Keys.Oemcomma
                || e.KeyCode == Keys.OemSemicolon)
            {
                string s = GetLastWord(this.rtbCmd.Text.Substring(0, rtbCmd.SelectionStart));
                s = s.ToLower();
                if (keyWords.IndexOf(s) > -1)
                {
                    int index = this.rtbCmd.SelectionStart;　　//记录修改的位置
                    this.rtbCmd.Select(this.rtbCmd.SelectionStart - s.Length, s.Length);
                    this.rtbCmd.SelectionColor = Color.Blue;
                    this.rtbCmd.SelectionFont = keyFont;
                    this.rtbCmd.Select(index, 0);　　 //返回修改的位置
                    this.rtbCmd.SelectionColor = Color.Black;
                    this.rtbCmd.SelectionFont = normalFont;
                }
            }

        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            StudentManagementSystem sm = new StudentManagementSystem(startUp.getIp().ToString() + ":" + startUp.getPort());
            sm.Show();
        }

        private void rtbCmd_TextChanged(object sender, EventArgs e)
        {
        }
    }
}
